﻿using System;
using System.Collections.Generic;
using System.IO;
using NetTopologySuite.Features;
using NetTopologySuite.IO;
using Newtonsoft.Json;
using netDxf;
using netDxf.Entities;
using netDxf.Header;
using netDxf.Tables;
using netDxf.Units;

namespace ConsoleApp
{
    public class GeoJsonToCadConverter
    {
        public void Convert(string geoJsonFilePath, string outputDxfFilePath)
        {
            // 1. 读取GeoJSON文件
            var geoJson = File.ReadAllText(geoJsonFilePath);
            var reader = new GeoJsonReader();

            // 2. 解析GeoJSON为特征集合
            FeatureCollection features;
            try
            {
                features = reader.Read<FeatureCollection>(geoJson);
            }
            catch (JsonException ex)
            {
                throw new InvalidOperationException("Invalid GeoJSON format", ex);
            }

            // 3. 创建DXF文档
            var dxf = new DxfDocument();
            dxf.DrawingVariables.InsUnits = DrawingUnits.Meters;

            // 4. 为不同类型的几何图形创建不同的图层
            var pointLayer = new Layer("Points") { Color = AciColor.Red };
            var lineLayer = new Layer("Lines") { Color = AciColor.Green };
            var polygonLayer = new Layer("Polygons") { Color = AciColor.Blue };
            var textLayer = new Layer("Text") { Color = AciColor.Cyan };

            // 5. 遍历所有特征并转换为DXF实体
            foreach (var feature in features)
            {
                var geometry = feature.Geometry;
                var attributes = feature.Attributes;

                switch (geometry.GeometryType)
                {
                    case "Point":
                        var point = geometry as NetTopologySuite.Geometries.Point;
                        var dxfPoint = new Point(new Vector2(point.X, point.Y));
                        dxfPoint.Layer = pointLayer;

                        // 添加属性文本
                        if (attributes.Count > 0)
                        {
                            var text = CreateAttributeText(point.X, point.Y, attributes);
                            text.Layer = textLayer;
                            dxf.AddEntity(text);
                        }

                        dxf.AddEntity(dxfPoint);
                        break;

                    case "LineString":
                        var lineString = geometry as NetTopologySuite.Geometries.LineString;
                        var vertices = ConvertCoordinates(lineString.Coordinates);
                        var dxfLine = new Polyline(vertices, false);
                        dxfLine.Layer = lineLayer;
                        dxf.AddEntity(dxfLine);
                        break;

                    case "Polygon":
                        var polygon = geometry as NetTopologySuite.Geometries.Polygon;
                        // 处理外环
                        var exteriorVertices = ConvertCoordinates(polygon.ExteriorRing.Coordinates);
                        var dxfPolygon = new Polyline(exteriorVertices, true);
                        dxfPolygon.Layer = polygonLayer;
                        dxf.AddEntity(dxfPolygon);

                        // 处理内环(孔洞)
                        for (int i = 0; i < polygon.NumInteriorRings; i++)
                        {
                            var interiorVertices = ConvertCoordinates(polygon.GetInteriorRingN(i).Coordinates);
                            var dxfHole = new Polyline(interiorVertices, true);
                            dxfHole.Layer = polygonLayer;
                            dxf.AddEntity(dxfHole);
                        }
                        break;

                    case "MultiPoint":
                    case "MultiLineString":
                    case "MultiPolygon":
                        // 处理多几何图形(递归处理每个子几何图形)
                        var multiGeometry = geometry as NetTopologySuite.Geometries.GeometryCollection;
                        foreach (var subGeometry in multiGeometry.Geometries)
                        {
                            var tempFeature = new Feature(subGeometry, attributes);
                            var tempCollection = new FeatureCollection();
                            tempCollection.Add(tempFeature);
                            ConvertFeatureCollection(tempCollection, dxf, pointLayer, lineLayer, polygonLayer, textLayer);
                        }
                        break;

                    default:
                        Console.WriteLine($"Unsupported geometry type: {geometry.GeometryType}");
                        break;
                }
            }

            // 6. 保存DXF文件
            dxf.Save(outputDxfFilePath);
        }

        private void ConvertFeatureCollection(FeatureCollection features, DxfDocument dxf, Layer pointLayer, Layer lineLayer, Layer polygonLayer, Layer textLayer)
        {
            foreach (var feature in features)
            {
                var geometry = feature.Geometry;
                var attributes = feature.Attributes;

                switch (geometry.GeometryType)
                {
                    case "Point":
                        var point = geometry as NetTopologySuite.Geometries.Point;
                        var dxfPoint = new Point(new Vector2(point.X, point.Y));
                        dxfPoint.Layer = pointLayer;
                        dxf.AddEntity(dxfPoint);
                        break;
                        // 其他情况类似...
                }
            }
        }

        private Vector3[] ConvertCoordinates(NetTopologySuite.Geometries.Coordinate[] coordinates)
        {
            var vertices = new Vector3[coordinates.Length];
            for (int i = 0; i < coordinates.Length; i++)
            {
                vertices[i] = new Vector3(coordinates[i].X, coordinates[i].Y, 0);// Z坐标设为0
            }
            return vertices;
        }

        private Text CreateAttributeText(double x, double y, IAttributesTable attributes)
        {
            var textContent = new System.Text.StringBuilder();
            foreach (var attributeName in attributes.GetNames())
            {
                textContent.AppendLine($"{attributeName}: {attributes[attributeName]}");
            }

            return new Text(textContent.ToString(), new Vector2(x, y), 0.5);
        }
    }
}